package com.maple.p2pclient.p2s;

import android.media.MediaCodecInfo;
import android.os.Bundle;
import android.widget.ListView;

import com.blankj.utilcode.util.GsonUtils;
import com.maple.p2pclient.R;
import com.maple.p2pclient.app.Const;
import com.maple.p2pclient.core.PeerConnectionObserverAdapter;
import com.maple.p2pclient.core.SdpObserverAdapter;
import com.maple.p2pclient.http.RetrofitClient;
import com.maple.p2pclient.http.bean.SrsRequestBean;
import com.maple.p2pclient.http.bean.SrsResponseBean;
import com.maple.p2pclient.socket.SocketType;
import com.maple.p2pclient.ui.MessageAdapter;
import com.maple.p2pclient.utils.LogUtils;
import com.maple.p2pclient.utils.WebRTCUtils;

import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.CameraVideoCapturer;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.MediaConstraints;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpTransceiver;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoEncoderSupportedCallback;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;

import java.util.ArrayList;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import static org.webrtc.DefaultVideoEncoderFactoryExtKt.createCustomVideoEncoderFactory;

public class P2SCameraActivity extends AppCompatActivity {

    private ListView lvList;
    private SurfaceViewRenderer localRenderer;
    private PeerConnectionFactory peerConnectionFactory;
    private PeerConnection peerConnection;

    private CameraVideoCapturer cameraVideoCapturer;

    private VideoTrack videoTrack;
    private AudioTrack audioTrack;

    private EglBase.Context eglBaseContext = EglBase.create().getEglBaseContext();

    private MessageAdapter listAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_p2s_camera);
        lvList = findViewById(R.id.lv_list);
        localRenderer = findViewById(R.id.svr_local_renderer);
        localRenderer.init(eglBaseContext,null);
        localRenderer.setMirror(true);

        listAdapter = new MessageAdapter(this,new ArrayList<String>());
        lvList.setAdapter(listAdapter);
        initRTC();
    }

    private void initRTC() {
        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();

        DefaultVideoEncoderFactory encoderFactory = createCustomVideoEncoderFactory(eglBaseContext, true, true, new VideoEncoderSupportedCallback() {
            @Override
            public boolean isSupportedH264(@NonNull MediaCodecInfo info) {
                return true;
            }
        });
        DefaultVideoDecoderFactory decoderFactory = new DefaultVideoDecoderFactory(eglBaseContext);
        peerConnectionFactory = PeerConnectionFactory
                .builder()
                .setOptions(options)
                .setVideoEncoderFactory(encoderFactory)
                .setVideoDecoderFactory(decoderFactory)
                .createPeerConnectionFactory();

        AudioSource createAudioSource = peerConnectionFactory.createAudioSource(WebRTCUtils.buildAudioConstraints());
        audioTrack = peerConnectionFactory.createAudioTrack("local_audio_track", createAudioSource);
        cameraVideoCapturer = WebRTCUtils.createVideoCapture(this);

        if(cameraVideoCapturer != null) {
            VideoSource videoSource = peerConnectionFactory.createVideoSource(cameraVideoCapturer.isScreencast());
            SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create("surface_texture_thread", eglBaseContext);
            cameraVideoCapturer.initialize(surfaceTextureHelper,this,videoSource.getCapturerObserver());
            //使用720P的分辨率
            cameraVideoCapturer.startCapture(localRenderer.getWidth(), localRenderer.getHeight(), 20);
            videoTrack = peerConnectionFactory.createVideoTrack("local_video_track",videoSource);
            // videoTrack.addSink(localRenderer);
        }
        PeerConnection.RTCConfiguration rtcConfig = WebRTCUtils.createRTCConfiguration();
        peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig, new PeerConnectionObserverAdapter(SocketType.CAMERA.getType()) {
            @Override
            public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
                super.onIceConnectionChange(iceConnectionState);
                LogUtils.logGGQ("camera onIceConnectionChange");
            }
        });

        if(peerConnection != null) {
            if(videoTrack != null) {
                peerConnection.addTransceiver(videoTrack,new RtpTransceiver.RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.SEND_ONLY));
            }
            if(audioTrack != null) {
                peerConnection.addTransceiver(audioTrack,new RtpTransceiver.RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.SEND_ONLY));
            }
        }

        if(videoTrack != null && !localRenderer.isActivated()) {
            videoTrack.addSink(localRenderer);
        }

        createOffer();

    }

    private void createOffer() {
        if(peerConnection != null) {
            peerConnection.createOffer(new SdpObserverAdapter("createOffer") {
                @Override
                public void onCreateSuccess(SessionDescription sdp) {
                    super.onCreateSuccess(sdp);
                    if(sdp != null && sdp.type == SessionDescription.Type.OFFER) {
                        peerConnection.setLocalDescription(new SdpObserverAdapter("setLocalDescription"),sdp);
                        String offerSdp = sdp.description;
                        SrsRequestBean requestBean = new SrsRequestBean();
                        requestBean.sdp = offerSdp;
                        requestBean.streamurl = Const.LIVE_URL;
                        try {
                            RetrofitClient retrofitClient = new RetrofitClient();
                            Call<SrsResponseBean> call = retrofitClient.getApiService(Const.BASE_URL).publish(requestBean);
                            LogUtils.logGGQ("url:" + call.request().url());
                            LogUtils.logGGQ("requestBean:" + GsonUtils.toJson(requestBean));

                            call.enqueue(new Callback<SrsResponseBean>() {
                                @Override
                                public void onResponse(@NonNull Call<SrsResponseBean> call, @NonNull Response<SrsResponseBean> response) {
                                    if (response.isSuccessful()) {
                                        SrsResponseBean responseBean = response.body();
                                        LogUtils.logGGQ("responseBean:" + GsonUtils.toJson(responseBean));
                                        if(responseBean != null && responseBean.code == 0) {
                                            LogUtils.logGGQ("publish 请求成功:" + response.code());
                                            String sdp = responseBean.sdp;
                                            SessionDescription remoteSdp = new SessionDescription(SessionDescription.Type.ANSWER, sdp);
                                            peerConnection.setRemoteDescription(new SdpObserverAdapter("setRemoteDescription"), remoteSdp);
                                            addItemList(GsonUtils.toJson(responseBean));
                                        } else {
                                            LogUtils.logGGQ("publish 请求失败1:" + response.code());
                                        }
                                    } else {
                                        LogUtils.logGGQ("publish 请求失败2:" + response.message());
                                    }
                                }

                                @Override
                                public void onFailure(@NonNull Call<SrsResponseBean> call, @NonNull Throwable t) {
                                    LogUtils.logGGQ("publish 请求错误:" + t.getMessage());
                                }
                            });
                        }catch (Exception e) {
                            LogUtils.logGGQ("publish 请求异常:" + e.getMessage());
                        }
                    }
                }
            },new MediaConstraints());

        }
    }


    private void addItemList(String item) {
        listAdapter.addItem(item);
        lvList.smoothScrollToPosition(listAdapter.getDataList().size() - 1);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(cameraVideoCapturer != null) {
            cameraVideoCapturer.dispose();
            try {
                cameraVideoCapturer.stopCapture();
                cameraVideoCapturer = null;
            } catch (InterruptedException e) {
                LogUtils.logGGQ("stopCapture");
            }
        }

        if(localRenderer != null) {
            localRenderer.release();
        }
        if(videoTrack != null) {
            videoTrack.dispose();
        }
        if(audioTrack != null) {
            audioTrack.dispose();
        }
        if(peerConnection != null) {
            peerConnection.dispose();
        }
        if(peerConnectionFactory != null) {
            peerConnectionFactory.dispose();
        }
    }
}